package com.jmxcfc.blfsc.common.validation;


import com.jmxcfc.blfsc.common.common.request.HeaderRequest;
import com.jmxcfc.blfsc.common.exception.ValidBodyException;
import com.jmxcfc.blfsc.common.exception.ValidException;
import com.jmxcfc.blfsc.common.exception.ValidHeaderException;
import com.jmxcfc.blfsc.common.sms.BaseContext;
import com.jmxcfc.blfsc.common.validation.rule.RequestFieldRule;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Objects;


/**
 * Request 校验器
 * 请求参数验证类型:不能是JSONObject,MAP类型,会导致反射过程无法获取到具体字段
 * 实现该类,可自主重写方法
 * @author pbs
 */
public interface IRequestValidator<B>{

    /**
     * 请求头验证
     * @param headerRequest 请求头参数
     * @param baseHandleContext
     * @param <E>
     */
    default <E> void validHeader(HeaderRequest headerRequest, BaseContext<E> baseHandleContext) {
        try {
            if (Objects.nonNull(baseHandleContext)) {
                baseHandleContext.getHeaderElementRules().forEach(rule -> valid(rule, headerRequest));
            }
        } catch (Exception e) {
            throw new ValidHeaderException(e.getMessage());
        }
    }
    /**
     * 请求体校验
     * B:请求参数(需要校验的数据类型)
     * E:为上线文的扩展字段
     * @param requestBody
     * @param baseHandleContext
     */
    default <E> void validBody(B requestBody, BaseContext<E> baseHandleContext) {
        try {
            if (Objects.nonNull(baseHandleContext)) {
                baseHandleContext.getBodyElementRules().forEach(rule -> valid(rule, requestBody));
            }
        } catch (Exception e) {
            throw new ValidBodyException(e.getMessage());
        }
    }

    /**
     * body扩展字段校验
     * 如果扩展字段是JSONObject 可以自主实现该类
     *
     * @param body 请求体(不能传JSONObject)
     *备注:每个实现类需要自己实现该方法,然后进行扩展字段的校验
     * @param baseHandleContext
     * @throws ValidBodyException
     */
    default <E> void validBodyExtend(B body, BaseContext<E> baseHandleContext) throws ValidBodyException {
       /* try {
            if (Objects.nonNull(baseHandleContext)) {
                baseHandleContext.getBodyExtendElementRules().forEach(rule -> valid(rule, bodyExtend));
            }
        } catch (Exception e) {
            throw new ValidBodyException(e.getMessage());
        }*/
    }

    /**
     * 合法校验
     *
     * @param rule
     * @param i
     * @param <I>
     * @throws ValidException
     */
    default <I, E> void valid(RequestFieldRule<E> rule, I i) throws ValidException {
        String fd = rule.getField();
        try {
            Field field = i.getClass().getDeclaredField(fd);
            PropertyDescriptor pd = new PropertyDescriptor(field.getName(), i.getClass());
            Method readMethod = pd.getReadMethod();
            E value = (E) readMethod.invoke(i);
            if (!rule.getRuleValidator().isValid(value)) {
                throw new ValidException(rule.getErrorDesc());
            }
        } catch (NoSuchFieldException | IllegalAccessException | RuntimeException | IntrospectionException |
                 InvocationTargetException e) {
            throw new ValidException(rule.getErrorDesc(), e);
        }
    }



}
